#if !defined(__NLS_NETWORK__) && defined(ONLINE)
#define __NLS_NETWORK__

#include <iostream>
#include <queue>
#include <string>
#include <SDL/SDL.h>
#include <errno.h>
#include "Endian.h"
#include "Types.h"

#ifdef _WIN32
# pragma comment(lib, "Ws2_32.lib")
#endif

using namespace std;

#ifdef _WIN32
# include <winsock2.h>
# include <windows.h>
# define CloseSocket closesocket
# define SocketIOControl ioctlsocket
# define NetworkError WSAGetLastError()
#else
# include <unistd.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <iomanp>
# define CloseSocket close
# define SocketIOControl fnctl
# define NetworkError errno
#endif

// TODO: fix these

#define HostToNetworkShort htons
#define HostToNetworkLong  htonl
#define NetworkToHostShort ntohs
#define NetworkToHostLong ntohl
#define InternetAddress inet_addr

namespace Network {

	class Packet;
	class CumulativeBuffer;

	typedef Packet* PACKET;
	
	bool initialize();

	void shutdown();

	void connectSocket(std::string, unsigned short);

	bool closeSocket();

	void writePacket(Packet*);

	int runSelector(void *unused);

	void ignite();
	
	///////////////////////////
	// PACKET CLASS
	///////////////////////////
	class Packet {
	private:
		unsigned int _position;
		unsigned int _capacity;
		unsigned int _pointer;
		char *data;
		void expandBuffer(int additionalBytes);
	public:
		Packet(int capacity = 32);
		~Packet();
		void writeByte(char val);
		void writeShort(short val);
		void writeInt(int val);
		void writeLong(__int64 val);
		void writeAsciiString(std::string &val);
		bool consumed();
		void incrementPointer(unsigned int);
		unsigned int position() { return _position; }
		unsigned int capacity() { return _capacity; }
		unsigned int pointer()  { return _pointer;  }
		char *packet();
	};

	//////////////////////////
	//   CUMULATIVE BUFFER  //
	//////////////////////////
	class CumulativeBuffer {
	private:
		char *_buf;
		unsigned int _position, _capacity;
	public:
		void appendData(char *data, unsigned int size);
	};
}

#endif //__NLS_NETWORK__